using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Navigation;
using Lib.Approval;
using Lib.Helper;
using Lib.Mail;
using MSIACCSL2.ApplicationStateServices;
using MSIACCSL2.Command;
using MSIACCSL2.InventoryAdjustmentServices;
using MSIACCSL2.InventoryServices;
using MSIACCSL2.ItemServices;
using MSIACCSL2.PalletServices;
using MSIACCSL2.SatuanServices;
using MSIACCSL2.Views.InventoryAdjustment;
using MSIACCSL2.WarehouseServices;
using WcfService1.DTO;
using GetListByCriteriaCompletedEventArgs = MSIACCSL2.InventoryAdjustmentServices.GetListByCriteriaCompletedEventArgs;
using GetListCompletedEventArgs = MSIACCSL2.InventoryAdjustmentServices.GetListCompletedEventArgs;
using SaveCompletedEventArgs = MSIACCSL2.InventoryAdjustmentServices.SaveCompletedEventArgs;

namespace MSIACCSL2.ViewModels
{
    public class InventoryAdjustmentViewModel : ViewModelBase
    {
        #region Delegates

        public delegate void Completed(Object param);

        #endregion

        private static Search frmSearch;
        private static string OrderType;
        private static string PropertySort;
        public static Mode mode;
        public static Completed OnSearchCompleted;
        private static NavigationService _NavigationService;
        private readonly AplicationStateServicesClient ApplicationService;
        private readonly ItemServicesClient ItemClient;
        private readonly PalletServicesClient PalletClient;
        private readonly WarehouseServicesClient WarehouseServicesClient;

        private readonly ValidationHandler validationHandler;
        private int CurrentPage;
        private InventoryServiceClient InventoryClient;
        private bool IsUsed;
        private ObservableCollection<int> Pages;
        private InventoryAdjustmentDTO _InventoryAdjustment;
        private InventoryAdjustmentDetailDTO _InventoryAdjustmentDetailCurrent;
        private PagedCollectionView _InventoryAdjustments;
        private bool _IsBusy;
        private bool _IsEnabled;
        private ObservableCollection<ItemDTO> _Items;
        private ObservableCollection<PurchaseInvoiceDTO> _PurchaseInvoices;
        private ObservableCollection<SupplierDTO> _Suppliers;
        private List<string> _errors;
        private Visibility _messageVisibility;
        private PagedCollectionView _pageSources;
        private InventoryAdjustmentServicesClient client;
        private Dictionary<string, object> criteria;
        private string expression;
        private bool _IsOut;
        private bool _IsIn;
        private ObservableCollection<WarehouseDTO> _Warehouses;

        public InventoryAdjustmentViewModel()
        {
            IsEnabled = true;

            if (!DesignerProperties.IsInDesignTool)
            {
                client = new InventoryAdjustmentServicesClient();
                ItemClient = new ItemServicesClient();
                PalletClient = new PalletServicesClient();
                InventoryClient = new InventoryServiceClient();
                OnPageChanged = new DelegateCommand(PageIndexChanged, CanPageIndexChanged);
                Save = new DelegateCommand(SaveInventoryAdjustment, CanSave);
                New = new DelegateCommand(NewInventoryAdjustment, CanNew);
                Unload = new DelegateCommand(Release, CanUnload);
                SearchCommand = new DelegateCommand(SearchInventoryAdjustment, CanSearch);
                SearchResultCommand = new DelegateCommand(SearchResult, CanSearchResult);
                CancelCommand = new DelegateCommand(Cancel, CanCancelCommand);
                GetTypeCommand = new DelegateCommand(GetTypeAdjusment, CanGetTypeCommand);
                validationHandler = new ValidationHandler();
                MessageVisibility = Visibility.Collapsed;
                Errors = new List<string>();
                ApplicationService = new AplicationStateServicesClient();
                WarehouseServicesClient = new WarehouseServicesClient();

                if (mode == Mode.Edit)
                    PrepareEdit();
                else if (mode == Mode.Search)
                    PrepareSearch();
                else if (mode == Mode.Add)
                    PrepareAdd();
                else
                    GetList(1, null);
            }
        }

        public PagedCollectionView InventoryAdjustments
        {
            get { return _InventoryAdjustments; }

            private set
            {
                if (InventoryAdjustments == value) return;
                _InventoryAdjustments = value;
                int i = (CurrentPage*30);
                foreach (object InventoryAdjustment in InventoryAdjustments)
                {
                    i += 1;

                    ((InventoryAdjustmentDTO) InventoryAdjustment).No = i;
                }
                FirePropertyChanged("InventoryAdjustments");
                InventoryAdjustments.CollectionChanged += InventoryAdjustment_CollectionChanged;
            }
        }

        public PagedCollectionView PageSources
        {
            get { return _pageSources; }
            private set
            {
                if (PageSources == value) return;
                _pageSources = value;
                FirePropertyChanged("PageSources");
            }
        }


        public ObservableCollection<PurchaseInvoiceDTO> PurchaseInvoices
        {
            get { return _PurchaseInvoices; }
            private set
            {
                if (PurchaseInvoices == value) return;
                _PurchaseInvoices = value;
                FirePropertyChanged("PurchaseInvoices");
            }
        }


        public ObservableCollection<SupplierDTO> Suppliers
        {
            get { return _Suppliers; }
            private set
            {
                if (Suppliers == value) return;
                _Suppliers = value;
                FirePropertyChanged("Suppliers");
            }
        }


        public bool IsBusy
        {
            get { return _IsBusy; }
            internal set
            {
                _IsBusy = value;
                FirePropertyChanged("IsBusy");
            }
        }


        public long RecordCount { get; set; }

        //Buat binding ke child form waktu mau edit
        public InventoryAdjustmentDTO InventoryAdjustment
        {
            get { return _InventoryAdjustment; }
            private set
            {
                if (InventoryAdjustment == value) return;
                _InventoryAdjustment = value;
                FirePropertyChanged("InventoryAdjustment");
            }
        }


        public ICommand OnPageChanged { get; set; }
        public ICommand Save { get; set; }
        public ICommand New { get; set; }
        public ICommand Edit { get; set; }
        public ICommand Unload { get; set; }
        public ICommand SearchCommand { get; set; }
        public ICommand SearchResultCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public ICommand GetTypeCommand { get; set; }

        public List<string> Errors
        {
            get { return _errors; }
            private set
            {
                if (Errors == value) return;
                _errors = value;
                FirePropertyChanged("Errors");
            }
        }

        public Visibility MessageVisibility
        {
            get { return _messageVisibility; }
            private set
            {
                if (MessageVisibility == value) return;
                _messageVisibility = value;
                FirePropertyChanged("MessageVisibility");
            }
        }

        public InventoryAdjustmentDetailDTO InventoryAdjustmentDetailCurrent
        {
            get { return _InventoryAdjustmentDetailCurrent; }
            private set
            {
                if (InventoryAdjustmentDetailCurrent == value) return;
                _InventoryAdjustmentDetailCurrent = value;
                FirePropertyChanged("InventoryAdjustmentDetailCurrent");
            }
        }

        public ObservableCollection<ItemDTO> Items
        {
            get { return _Items; }
            set
            {
                if (Items == value) return;
                _Items = value;
                FirePropertyChanged("Items");
            }
        }

        public bool IsEnabled
        {
            get { return _IsEnabled; }
            internal set
            {
                _IsEnabled = value;
                FirePropertyChanged("IsEnabled");
            }
        }

        public bool IsIn
        {
            get { return _IsIn; }
            internal set
            {
                _IsIn = value;
                FirePropertyChanged("IsIn");
            }
        }

        public bool IsOut
        {
            get { return _IsOut; }
            internal set
            {
                _IsOut = value;
                FirePropertyChanged("IsOut");
            }
        }

        public ICommand LoadPICommand { get; set; }

        private void PrepareEdit()
        {
            InventoryAdjustment = (InventoryAdjustmentDTO) Navigation.Args;
            client.GetInventoryAdjustmentCompleted += new EventHandler<GetInventoryAdjustmentCompletedEventArgs>(client_GetInventoryAdjustmentCompleted);
            client.GetInventoryAdjustmentAsync(InventoryAdjustment.NoAdj);
           
            if (InventoryAdjustment.InventoryAdjustmentDetails == null)
                InventoryAdjustment.InventoryAdjustmentDetails =
                    new ObservableCollection<InventoryAdjustmentDetailDTO>();
            if (InventoryAdjustment.InventoryAdjustmentDetails.Count == 0)
                InventoryAdjustment.InventoryAdjustmentDetails.Add(new InventoryAdjustmentDetailDTO());
            CekTransaksi();

            if (InventoryAdjustment.Type == "in")
                IsIn = true;
            else
                IsOut = true;

          
        }

        void client_GetInventoryAdjustmentCompleted(object sender, GetInventoryAdjustmentCompletedEventArgs e)
        {
            client.GetInventoryAdjustmentCompleted -= new EventHandler<GetInventoryAdjustmentCompletedEventArgs>(client_GetInventoryAdjustmentCompleted);
            InventoryAdjustment = e.Result;
            GetWarehouseList();
        }

        private void PrepareAdd()
        {
            //GetLastNoInventoryAdjustment();
            InventoryAdjustment = new InventoryAdjustmentDTO();
            InventoryAdjustment.InventoryAdjustmentDetails = new ObservableCollection<InventoryAdjustmentDetailDTO>();
            var InventoryAdjustmentDetail = new InventoryAdjustmentDetailDTO();
            InventoryAdjustmentDetail.Inventory = new InventoryDTO();
            InventoryAdjustmentDetail.Inventory.Item = new ItemDTO();
            InventoryAdjustment.InventoryAdjustmentDetails.Add(InventoryAdjustmentDetail);
            GetWarehouseList();
            //CekTransaksi();
        }

        private void PrepareSearch()
        {
            InventoryAdjustment = new InventoryAdjustmentDTO();
            InventoryAdjustment.TglAdjustment = null;
        }

        public bool CanGetTypeCommand(Object param)
        {
            return true;
        }

        public void Complete(Object param)
        {
            OnSearchCompleted(param);
        }

        private void InventoryAdjustment_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (((PagedCollectionView) sender).SortDescriptions.Count > 0)
            {
                if (((PagedCollectionView) sender).SortDescriptions[0].PropertyName.ToLower() == "no") return;

                PropertySort = ((PagedCollectionView) sender).SortDescriptions[0].PropertyName;
                if (string.IsNullOrEmpty(OrderType))
                {
                    OrderType = "ASC";
                }
                else
                {
                    OrderType = OrderType == "ASC" ? OrderType = "DESC" : OrderType = "ASC";
                }
                GetList(1, PropertySort);
            }
        }


        public void SaveInventoryAdjustment(Object inventoryAdjustment)
        {
            //InventoryAdjustment = (InventoryAdjustmentDTO) inventoryAdjustment;
            if (InventoryAdjustment.InventoryAdjustmentDetails.Count == 1)
            {
                //Bila tidak ada yang dipilih di detail maka details harus dihapus
                if (InventoryAdjustment.InventoryAdjustmentDetails[0].Inventory == null)
                    InventoryAdjustment.InventoryAdjustmentDetails.Clear();
            }
            Validate();
            if (Errors.Count > 0) return;
            InventoryAdjustment.created_by = GlobalVar.User.UserID;
            InventoryAdjustment.modified_by = GlobalVar.User.UserID;
            IsBusy = true;
            client.SaveCompleted += client_SaveCompleted;
            client.SaveAsync(InventoryAdjustment, mode);
        }

        private void client_SaveCompleted(object sender, SaveCompletedEventArgs e)
        {
            if (e.Error != null) Validate(e.Error.ToString());
            client.SaveCompleted -= client_SaveCompleted;
            mode = (Mode) e.UserState;
            IsBusy = false;

            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
                return;
            }

            if (e.Result)
            {
                IsBusy = false;
                ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.Navigate(new Uri("/InventoryAdjustment/Index", UriKind.Relative));
            }
          
        }


        public void GetList(int? page, string sortProp)
        {
            IsBusy = true;
            client.GetListCompleted += client_GetListCompleted;
            client.GetListAsync(page ?? 1, sortProp, OrderType);
        }

        private void client_GetListCompleted(object sender, GetListCompletedEventArgs e)
        {
            RecordCount = e.recordCount;
            if (PageSources == null) CreatePageNumber();
            client.GetListCompleted -= client_GetListCompleted;
            InventoryAdjustments = new PagedCollectionView(e.Result);
            IsBusy = false;
            Complete(this);
        }


        private void NewInventoryAdjustment(Object param)
        {
            mode = Mode.Add;
            Navigation.MyNavigation = (NavigationService) param;
            Navigation.MyNavigation.Navigate(new Uri("/InventoryAdjustment/frmAdd", UriKind.Relative));
        }


        private void SearchInventoryAdjustment(Object param)
        {
            mode = Mode.Search;
            frmSearch = new Search();
            frmSearch.Show();
        }


        private void SearchResult(Object param)
        {
            criteria = new Dictionary<string, object>();

            foreach (PropertyInfo prop in InventoryAdjustment.GetType().GetProperties())
            {
                if (prop.PropertyType == typeof (Decimal))
                {
                    if ((Decimal) prop.GetValue(InventoryAdjustment, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Int32))
                {
                    if ((Int32) prop.GetValue(InventoryAdjustment, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Int64))
                {
                    if ((Int64) prop.GetValue(InventoryAdjustment, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Double))
                {
                    if ((Double) prop.GetValue(InventoryAdjustment, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (String))
                {
                    if (String.IsNullOrEmpty((String) prop.GetValue(InventoryAdjustment, null))) continue;
                }
                if (prop.PropertyType == typeof (DateTime))
                {
                    if (prop.GetValue(InventoryAdjustment, null).ToString().Contains("0001")) continue;
                }
                if (prop.GetValue(InventoryAdjustment, null) == null) continue;
                if (prop.PropertyType.Name == "No") continue;

                if (prop.PropertyType.Name.ToLower().Contains("dto"))
                {
                    foreach (
                        PropertyInfo propertyInfo in prop.GetValue(InventoryAdjustment, null).GetType().GetProperties()
                        )
                    {
                        if (propertyInfo.Name.ToLower().Contains("id") || propertyInfo.Name.ToLower().Contains("kode") ||
                            propertyInfo.Name.ToLower().Contains("serial") ||
                            propertyInfo.Name.ToLower().Contains("code"))
                        {
                            criteria.Add(prop.Name,
                                         propertyInfo.GetValue(prop.GetValue(InventoryAdjustment, null), null));
                            break;
                        }
                    }
                }
                else
                {
                    criteria.Add(prop.Name, prop.GetValue(InventoryAdjustment, null));
                }
            }

            expression = string.Empty;
            if (frmSearch.rblOr.IsChecked ?? false) expression = "OR";
            else expression = "AND";
            InventoryAdjustmentSearch(criteria, expression,1);
        }

        private void InventoryAdjustmentSearch(Dictionary<String, Object> criteria, string expression,int page)
        {
            frmSearch.DialogResult = true;
            IsBusy = true;
            Complete(this);
            client.GetListByCriteriaCompleted += client_GetListByCriteriaCompleted;
            client.GetListByCriteriaAsync(criteria, expression, page);
        }

        private void client_GetListByCriteriaCompleted(object sender, GetListByCriteriaCompletedEventArgs e)
        {
            client.GetListByCriteriaCompleted -= client_GetListByCriteriaCompleted;
            InventoryAdjustments = new PagedCollectionView(e.Result);
            if (RecordCount != e.recordCount)
            {
                RecordCount = e.recordCount;
                CreatePageNumber();
            }
            IsBusy = false;
        }


        private void CreatePageNumber()
        {
            Pages = new ObservableCollection<int>();
            for (int i = 0; i < RecordCount; i++)
            {
                Pages.Add(i);
            }
            PageSources = new PagedCollectionView(Pages);
        }


        private void PageIndexChanged(Object pageIndex)
        {
            //Jika Pertama kali jangan di Getlagi
            InventoryAdjustment = null;
            if (InventoryAdjustments != null && CurrentPage != (int) pageIndex)
            {
                CurrentPage = (int) pageIndex;
                if (mode == Mode.Search)
                    InventoryAdjustmentSearch(criteria, expression, (int)pageIndex + 1);
                else if (String.IsNullOrEmpty(PropertySort))
                    GetList((int) pageIndex + 1, null);
                else GetList((int) pageIndex + 1, PropertySort);
            }
        }


        public bool CanPageIndexChanged(Object param)
        {
            return true;
        }


        public bool CanSave(Object param)
        {
            return true;
        }


        public bool CanNew(Object param)
        {
            return true;
        }

        public bool CanEdit(Object param)
        {
            return true;
        }


        public bool CanUnload(Object param)
        {
            return true;
        }


        public bool CanSearch(Object param)
        {
            return true;
        }

        public bool CanSearchResult(Object param)
        {
            return true;
        }

        public bool CanCancelCommand(Object param)
        {
            return true;
        }


        public void Release(Object param)
        {
            param = null;
            InventoryAdjustment = null;
            OrderType = null;
            PropertySort = null;
            mode = Mode.Idle;
        }


        public void Refresh()
        {
            if (InventoryAdjustments == null)
                GetList(1, null);
            else
                Complete(this);
        }


        public void Validate(string error = null)
        {
            Errors = new List<string>();
            //if (string.IsNullOrEmpty(InventoryAdjustment.NoAdj))
            //    Errors.Add("Nomor Adjustment tidak boleh kosong");

            foreach (var detail in InventoryAdjustment.InventoryAdjustmentDetails)
                if (detail.Warehouse == null)
                    Errors.Add("Warehouse belum dipilih!");

            if (!string.IsNullOrEmpty(error))
                Errors.Add(error);

            if (Errors.Count > 0)
            {
                MessageVisibility = Visibility.Visible;
            }
            else
            {
                MessageVisibility = Visibility.Collapsed;
            }
        }

        public void Cancel(Object param)
        {
            MessageBoxResult res = MessageBox.Show("Are You Sure Want to Cancel ?", "Confirmation",
                                                   MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                if (!IsUsed) ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.GoBack();
            }
        }

        private void GetLastNoInventoryAdjustment()
        {
            client = new InventoryAdjustmentServicesClient();
            client.GetLastNoAdjustmentCompleted += client_GetLastNoAdjustmentCompleted;
            client.GetLastNoAdjustmentAsync();
        }

        private void client_GetLastNoAdjustmentCompleted(object sender, GetLastNoAdjustmentCompletedEventArgs e)
        {
            client.GetLastNoAdjustmentCompleted -= client_GetLastNoAdjustmentCompleted;
            string res = e.Result;
            string formatSO = "0000";
            string kodeSO;
            if (e.Result.Length <= 4)
            {
                res = formatSO;
                kodeSO = e.Result;
            }
            else
            {
                res = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[2];
                kodeSO = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[0];
            }
            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(res) + 1).ToString().Length) +
                           (int.Parse(res) + 1);
            InventoryAdjustment.NoAdj = kodeSO + "/" + DateTime.Now.Year + "/" + soNum;
        }

        public void GetItemByName(Object param)
        {
            if (param.GetType() == typeof (InventoryAdjustmentDetailDTO))
            {
                InventoryAdjustmentDetailCurrent = param as InventoryAdjustmentDetailDTO;
                ItemClient.GetItemByNameCompleted += ItemClient_GetItemByNameCompleted;
                ItemClient.GetItemByNameAsync(InventoryAdjustmentDetailCurrent.Inventory.Item.ItemName);
            }
            else
            {
                ItemClient.GetItemByNameCompleted += ItemClient_GetItemByNameCompleted;
                ItemClient.GetItemByNameAsync(param.ToString());
            }
        }

        private void ItemClient_GetItemByNameCompleted(object sender, GetItemByNameCompletedEventArgs e)
        {
            ItemClient.GetItemByNameCompleted -= ItemClient_GetItemByNameCompleted;
            Items = e.Result;
        }

        public void GetPalletByWarehouse(Object param)
        {
            var InventoryAdjustmentDetail = param as InventoryAdjustmentDetailDTO;
            PalletClient.GetPalletByWarehouseCompleted += PalletClient_GetPalletByWarehouseCompleted;
            PalletClient.GetPalletByWarehouseAsync(InventoryAdjustmentDetail.Warehouse, InventoryAdjustmentDetail);
        }

        private void PalletClient_GetPalletByWarehouseCompleted(object sender, GetPalletByWarehouseCompletedEventArgs e)
        {
            var InventoryAdjustmentDetail = e.UserState as InventoryAdjustmentDetailDTO;
            InventoryAdjustmentDetail.Pallets = e.Result;
        }

        public void GetTypeAdjusment(Object param)
        {
            if (param.ToString() == "In")
                InventoryAdjustment.Type = "In";
            else
                InventoryAdjustment.Type = "Out";
        }


        public void SendEmail(Object param)
        {
            ChooseDestination chooseDestination = new ChooseDestination();
            chooseDestination.Show();
            EventAggregator.RegisterMessage("SendDestination", (x) =>
            {
                IsBusy = true;
                client.SendEmailCompleted += client_SendEmailCompleted;
                client.SendEmailAsync(param as InventoryAdjustmentDTO, (x as WarehouseDTO).EmailFolder);
            });
            
        }

        private void client_SendEmailCompleted(object sender, InventoryAdjustmentServices.SendEmailCompletedEventArgs e)
        {
            IsBusy = false;
            client.SendEmailCompleted -= client_SendEmailCompleted;
            if (e.Result) MessageBox.Show("Pengiriman Selesai");
        }

        public void CekTransaksi()
        {
            ApplicationService.IsTransactionUsedCompleted += ApplicationService_IsTransactionUsedCompleted;
            if (string.IsNullOrEmpty(InventoryAdjustment.NoAdj))
            {
                ApplicationService.IsTransactionUsedAsync(InventoryAdjustment.ToString(), GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = InventoryAdjustment.ToString();
            }
            else
            {
                ApplicationService.IsTransactionUsedAsync(InventoryAdjustment.NoAdj, GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = InventoryAdjustment.NoAdj;
            }
        }

        private void ApplicationService_IsTransactionUsedCompleted(object sender, IsTransactionUsedCompletedEventArgs e)
        {
            ApplicationService.IsTransactionUsedCompleted -= ApplicationService_IsTransactionUsedCompleted;
            IsUsed = e.Result;
            mode = (Mode) e.UserState;
            if (IsUsed)
            {
                MessageBox.Show("Transaksi sedang digunakan!");
                if (mode == Mode.Add) //If Add Mode
                {
                    mode = Mode.Idle;
                    Navigation.MyNavigation.Navigate(new Uri("/InventoryAdjustment/Index", UriKind.Relative));
                }
                else //Edit Mode just view Only
                {
                    IsEnabled = false;
                }
            }
        }

        private void ClearTransaksi(Mode mode)
        {
            ApplicationService.ClearTransactionCompleted += ApplicationService_ClearTransactionCompleted;
            if (mode == Mode.Add)
                ApplicationService.ClearTransactionAsync(InventoryAdjustment.ToString(), GlobalVar.User);
            else
                ApplicationService.ClearTransactionAsync(InventoryAdjustment.NoAdj, GlobalVar.User);
        }

        private void ApplicationService_ClearTransactionCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ApplicationService.ClearTransactionCompleted -= ApplicationService_ClearTransactionCompleted;
        }

        public void CloseStatus()
        {
            MessageBoxResult res = MessageBox.Show("Are You Sure Want to Close this Transaction ?", "Confirmation",
                                                MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                client.UpdateStatusCompleted += new EventHandler<AsyncCompletedEventArgs>(client_UpdateStatusCompleted);
                client.UpdateStatusAsync(InventoryAdjustment, Status.Close);
            }
        }

        void client_UpdateStatusCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.UpdateStatusCompleted -= new EventHandler<AsyncCompletedEventArgs>(client_UpdateStatusCompleted);
            MessageBox.Show("Update Status finished!");
        }


        public void GetWarehouseList()
        {
            WarehouseServicesClient.GetListByCriteriaCompleted +=
                WarehouseClient_GetListByCriteriaCompleted;
            WarehouseServicesClient.GetListByCriteriaAsync(new Dictionary<string, object>(), null, 1);
        }

        private void WarehouseClient_GetListByCriteriaCompleted(object sender,
                                                                WarehouseServices.GetListByCriteriaCompletedEventArgs e)
        {
            if (InventoryAdjustment != null)
            {
                foreach (
                    InventoryAdjustmentDetailDTO InventoryAdjustmentDetail in
                        InventoryAdjustment.InventoryAdjustmentDetails)
                {
                    InventoryAdjustmentDetail.Warehouses = e.Result;
                    if (InventoryAdjustmentDetail.Warehouse == null) continue;
                    InventoryAdjustmentDetail.Warehouse =
                        e.Result.FirstOrDefault(
                            s => s.KodeWarehouse == InventoryAdjustmentDetail.Warehouse.KodeWarehouse);
                }
            }
        }
      
    }


    public class InventoryAdjustmentWrapViewModel : ViewModelBase
    {
        private readonly InventoryServiceClient Inventoryclient;
        private readonly ItemServicesClient ItemClient;
        private readonly PalletServicesClient PalletClient;
        private readonly SatuanServicesClient SatuanClient;
        private readonly WarehouseServicesClient WarehouseServicesClient;
        private readonly InventoryAdjustmentServicesClient client;
        private InventoryAdjustmentDetailDTO _InventoryAdjustmentDetail;
        private ObservableCollection<ItemDTO> _Items;
        private ObservableCollection<SatuanDTO> _SatuanPacks;
        private ObservableCollection<SatuanDTO> _SatuanUnits;
        private ObservableCollection<WarehouseDTO> _Warehouses;


        public InventoryAdjustmentWrapViewModel()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                EditCommand = new DelegateCommand(Edit, CanEditCommand);
                DeleteCommand = new DelegateCommand(Delete, CanDeleteCommand);
                client = new InventoryAdjustmentServicesClient();
                ItemClient = new ItemServicesClient();
                PalletClient = new PalletServicesClient();
                SatuanClient = new SatuanServicesClient();
                WarehouseServicesClient = new WarehouseServicesClient();
                Inventoryclient = new InventoryServiceClient();

                AddDetailCommand = new DelegateCommand(AddInventoryAdjustmentDetail, CanAddDetailCommand);
                DeleteDetailCommand = new DelegateCommand(DeleteInventoryAdjustmentDetail, CanDeleteDetailCommand);
                GetQtyUnitCommand = new DelegateCommand(GetQtyUnit, CanGetQtyUnit);
                if (InventoryAdjustmentViewModel.mode == Mode.Add || InventoryAdjustmentViewModel.mode == Mode.Edit)
                {
                    GetSatuanPackList(); 
                }
            }
        }

        public InventoryAdjustmentViewModel InventoryAdjustmentViewModel { get; set; }


        public ICommand EditCommand { get; set; }
        public ICommand DeleteCommand { get; set; }
        public ICommand AddDetailCommand { get; set; }
        public ICommand DeleteDetailCommand { get; set; }
        public ICommand GetQtyUnitCommand { get; set; }


        public ObservableCollection<ItemDTO> Items
        {
            get { return _Items; }
            private set
            {
                if (Items == value) return;
                _Items = value;
                FirePropertyChanged("Items");
            }
        }


        public ObservableCollection<SatuanDTO> SatuanPacks
        {
            get { return _SatuanPacks; }
            private set
            {
                if (SatuanPacks == value) return;
                _SatuanPacks = value;
                FirePropertyChanged("SatuanPacks");
            }
        }


        public ObservableCollection<SatuanDTO> SatuanUnits
        {
            get { return _SatuanUnits; }
            private set
            {
                if (SatuanUnits == value) return;
                _SatuanUnits = value;
                FirePropertyChanged("SatuanUnits");
            }
        }


        public ObservableCollection<WarehouseDTO> Warehouses
        {
            get { return _Warehouses; }
            private set
            {
                if (Warehouses == value) return;
                _Warehouses = value;
                FirePropertyChanged("Warehouses");
            }
        }


        public InventoryAdjustmentDetailDTO InventoryAdjustmentDetail
        {
            get { return _InventoryAdjustmentDetail; }
            private set
            {
                if (InventoryAdjustmentDetail == value) return;
                _InventoryAdjustmentDetail = value;
                FirePropertyChanged("InventoryAdjustmentDetail");
            }
        }

        public bool CanEditCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteCommand(Object param)
        {
            return true;
        }

        public bool CanAddDetailCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteDetailCommand(Object param)
        {
            return true;
        }


        public void Edit(Object param)
        {
            InventoryAdjustmentViewModel.mode = Mode.Edit;
            Navigation.MyNavigation.Navigate(new Uri("/InventoryAdjustment/frmAdd", UriKind.Relative));
            Navigation.Args = param;
        }

        public void Delete(Object param)
        {

            DeleteConfirmation deleteConfirmation = new DeleteConfirmation();
            deleteConfirmation.Show();
            EventAggregator.RegisterMessage("ApprovalSucceeded", (x) =>
            {
                deleteConfirmation.Close();
                client.DeleteCompleted += client_DeleteCompleted;
                client.DeleteAsync((InventoryAdjustmentDTO)param);
            });
        }

        private void client_DeleteCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.DeleteCompleted -= client_DeleteCompleted;
            MessageBox.Show("Delete Success!");
            InventoryAdjustmentViewModel.mode = Mode.Idle;
            var VM = new InventoryAdjustmentViewModel();
        }


        public void GetSatuanPackList()
        {
            SatuanClient.GetListByCriteriaCompleted +=
                SatuanClient_GetListByCriteriaCompleted;
            SatuanClient.GetListByCriteriaAsync(new Dictionary<string, object>(), null, 1);
        }

        private void SatuanClient_GetListByCriteriaCompleted(object sender,
                                                             SatuanServices.GetListByCriteriaCompletedEventArgs
                                                                 e)
        {
            SatuanPacks = e.Result;
            SatuanUnits = e.Result;

            if (InventoryAdjustmentViewModel.InventoryAdjustment != null)
            {
                foreach (
                    InventoryAdjustmentDetailDTO InventoryAdjustmentDetail in
                        InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails)
                {
                    if (InventoryAdjustmentDetail.Inventory != null)
                    {
                        if (InventoryAdjustmentDetail.Inventory.SatuanPack == null) continue;
                        InventoryAdjustmentDetail.Inventory.SatuanPack =
                            SatuanPacks.FirstOrDefault(
                                s => s.KodeSatuan == InventoryAdjustmentDetail.Inventory.SatuanPack.KodeSatuan);
                        InventoryAdjustmentDetail.Inventory.SatuanUnit =
                            SatuanUnits.FirstOrDefault(
                                s => s.KodeSatuan == InventoryAdjustmentDetail.Inventory.SatuanUnit.KodeSatuan);
                    }
                }
            }
        }

      
        public void AddInventoryAdjustmentDetail(Object param)
        {
            InventoryAdjustmentDetail = new InventoryAdjustmentDetailDTO();
            var adjFirst = InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails.FirstOrDefault();
            if (adjFirst != null)
                if (adjFirst.Warehouses != null) 
                    InventoryAdjustmentDetail.Warehouses = adjFirst.Warehouses;
            InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails.Add(InventoryAdjustmentDetail);
        }

        public void DeleteInventoryAdjustmentDetail(Object param)
        {
            var InventoryAdjustmentDetail = (InventoryAdjustmentDetailDTO) param;

            if (InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails.Count > 1)
            {
                if (param ==null)
                {
                    int count = InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails.Count;
                    InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails.RemoveAt(count-1);
                }else
                {
                    InventoryAdjustmentViewModel.InventoryAdjustment.InventoryAdjustmentDetails.Remove(
                   InventoryAdjustmentDetail);
                }
            }
        }

      


        public bool CanGetInventoryCommand(Object param)
        {
            return true;
        }

        public void GetInventory(Object param)
        {
            InventoryAdjustmentDetail = (InventoryAdjustmentDetailDTO) param;
            if (InventoryAdjustmentDetail.Inventory == null) InventoryAdjustmentDetail.Inventory = new InventoryDTO();
            string SerialNumber = InventoryAdjustmentDetail.Inventory.SerialNumber;
            Inventoryclient.GetInventoryCompleted +=
                InventoryClient_GetInventoryCompleted;
            Inventoryclient.GetInventoryAsync(SerialNumber);
        }

        private void InventoryClient_GetInventoryCompleted(object sender, GetInventoryCompletedEventArgs e)
        {
            Inventoryclient.GetInventoryCompleted -=
                InventoryClient_GetInventoryCompleted;
            if (null != e.Result && ! string.IsNullOrEmpty(e.Result.SerialNumber))
            {
                InventoryAdjustmentDetail.Inventory = e.Result;
                InventoryAdjustmentDetail.Panjang = e.Result.Panjang;
                InventoryAdjustmentDetail.Lebar = e.Result.Lebar;
                InventoryAdjustmentDetail.Tinggi = e.Result.Warehouses.FirstOrDefault().Sheet;
                InventoryAdjustmentDetail.QtyUnit = e.Result.Warehouses.FirstOrDefault().Qty;
                InventoryAdjustmentDetail.Price = e.Result.UnitPrice;
                InventoryAdjustmentDetail.Items = new ObservableCollection<ItemDTO>();
                if (e.Result.Item != null)
                {
                    InventoryAdjustmentDetail.Items.Add(e.Result.Item);
                    InventoryAdjustmentDetail.Inventory.Item = e.Result.Item;
                }

                if (e.Result.SatuanPack != null)
                    InventoryAdjustmentDetail.Inventory.SatuanPack =
                        SatuanPacks.FirstOrDefault(x => x.KodeSatuan == e.Result.SatuanPack.KodeSatuan);
                if (e.Result.SatuanUnit != null)
                    InventoryAdjustmentDetail.Inventory.SatuanUnit =
                        SatuanUnits.FirstOrDefault(x => x.KodeSatuan == e.Result.SatuanUnit.KodeSatuan);
            }else
            {
                MessageBox.Show("Barang tidak ditemukan, coba entry secara manual");
            }
        }


        public bool CanGetQtyUnit(Object param)
        {
            return true;
        }

        public void GetQtyUnit(Object param)
        {
            InventoryAdjustmentDetail = (InventoryAdjustmentDetailDTO) param;
            if (InventoryAdjustmentDetail.Inventory != null && ! string.IsNullOrEmpty(InventoryAdjustmentDetail.Inventory.SerialNumber) )
            {
                Decimal pengali = InventoryAdjustmentDetail.Inventory.SatuanUnit != null
                                      ? InventoryAdjustmentDetail.Inventory.SatuanUnit.Pengali
                                      : 1;
                if (pengali == 0) pengali = 1;
                InventoryAdjustmentDetail.QtyUnit = InventoryAdjustmentDetail.Inventory.QtyPack*
                                                              (InventoryAdjustmentDetail.Panjang*
                                                               InventoryAdjustmentDetail.Lebar*
                                                               InventoryAdjustmentDetail.Tinggi)/pengali;


                InventoryAdjustmentDetail.QtyUnit = InventoryAdjustmentDetail.Inventory.Item.IsRounded
                                                        ? InventoryAdjustmentDetail.QtyUnit.Round(2,
                                                                                                  MidpointRounding.
                                                                                                      AwayFromZero)
                                                        : InventoryAdjustmentDetail.QtyUnit.Round(4,
                                                                                                  MidpointRounding.
                                                                                                      AwayFromZero);
            }
        }
    }
}